package dawi.fcs.servicio.generico;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.servlet.ServletContext;

import org.apache.struts2.ServletActionContext;

import dawi.fcs.dominio.CorreoAdjuntos;

/**
 * 
 * Clase que se encarga del envio de correos.
 */

public class NEnvioCorreo {

	/**
	 * 
	 * Ruta de la carpeta temporal donde la clase ira creando las carpetas
	 * temporales necesarias
	 * 
	 * para la generacion de los archivos que iran como adjuntos en el correo
	 * electronico.
	 */

	private static final String CARPETA_TEMPORAL = "dawi" + File.separator
			+ "fcs" + File.separator + "servicio" + File.separator + "servicio"
			+ File.separator;

	private static String mensajeInterno;

	private static Boolean flagAdjuntoArchivos = false;

	/**
	 * 
	 * Constructor NEnvioCorreo.
	 */

	public NEnvioCorreo() {

	}

	public static String enviarEmailMensajeHTML(

	String sCadenaConfigCorreo,

	String sCorreoRemitente,

	String sCorreosDestino,

	String sCorreosDestinoCc,

	String sAsunto,

	ResultSet sMensajeRS,

	String sSeparadorCorreos) throws SQLException {

		String _mensaje = "";

		try {

			while (sMensajeRS.next()) {

				_mensaje = new String(sMensajeRS.getBytes(2), "ISO-8859-1");

				break;

			}

			// se comenta por que da problemas en el objeto package

			// sMensajeRS.close();

		} catch (Exception ex) {

			_mensaje = "0 - ";

			_mensaje = _mensaje + ex.getMessage();

			return _mensaje;

		}

		// _mensaje = ".." + _mensaje;

		return enviarEmail(

		sCadenaConfigCorreo,

		sCorreoRemitente,

		sCorreosDestino,

		sCorreosDestinoCc,

		sAsunto,

		_mensaje,

		sSeparadorCorreos, null);

	}

	/**
	 * 
	 * Envia un correo electronico con adjunto(s).
	 * 
	 * @param sCadenaConfigCorreo
	 *            texto con la configuracion que se requiere para enviar
	 * 
	 *            el correo a traves de STMP. Por ejemplo:</br>
	 * 
	 *            <i>mail.smtp.host=urano.royalsystems.net</br>
	 * 
	 *            mail.smtp.user=panayfor@royalsystems.net</br>
	 * 
	 *            mail.smtp.auth=true</br>
	 * 
	 *            mail.smtp.password=roger1234</i></br>
	 * 
	 * @param sCorreoRemitente
	 *            correo que se usara como remitente
	 * 
	 * @param sCorreosDestino
	 *            lista de correos electronicos destinatarios separados por un
	 *            caracter,
	 * 
	 *            por ejemplo:
	 *            <i>usuario@compania.com,administrador@compania.com</i>
	 * 
	 * @param sCorreosDestinoCc
	 *            lista de correos electronicos a los cuales se les copia, los
	 *            cuales
	 * 
	 *            estan separados por un caracter, por ejemplo:
	 *            <i>usuariocopia@compania.com,
	 * 
	 *            administradorcopia@compania.com</i>
	 * 
	 * @param sAsunto
	 *            asunto del correo electronico
	 * 
	 * @param sMensaje
	 *            texto que se mostrara en el cuerpo del correo electronico
	 * 
	 * @param sSeparadorCorreos
	 *            caracter que separa la lista de correos destinatarios y
	 *            correos
	 * 
	 *            copia
	 * 
	 * @param adjuntos
	 *            resulSet con la lista de archivos BLOB (tipo de dato de oracle
	 *            que contiene
	 * 
	 *            los binarios de los archivos que se enviaran por correo)
	 * 
	 * @return
	 */

	@SuppressWarnings({ "rawtypes", "unused" })
	public static String enviarEmail(

	String sCadenaConfigCorreo,

	String sCorreoRemitente,

	String sCorreosDestino,

	String sCorreosDestinoCc,

	String sAsunto,

	String sMensaje,

	String sSeparadorCorreos,

	List<CorreoAdjuntos> adjuntos) {

		// Antes de iniciar con toda la logica, se validan que todos los
		// parametros

		// tengan valores.
		sCadenaConfigCorreo = "mail.smtp.host=smtp.gmail.com"
				+ "\nmail.smtp.user=gestionjuri@gmail.com"
				+ "\nmail.smtp.auth=true" + "\nmail.smtp.password=cibertec123";
		String validacion = validarParametros(

		sCadenaConfigCorreo,

		sCorreoRemitente,

		sCorreosDestino,

		sCorreosDestinoCc,

		sAsunto,

		sMensaje,

		sSeparadorCorreos);

		if (!estaVacio(validacion))

			throw new RuntimeException(validacion);

		String _retorno = "";

		// Se convierten los correos en vectores.

		Vector toCorreo = split(sCorreosDestino, sSeparadorCorreos);

		Vector ccCorreo = split(sCorreosDestinoCc, sSeparadorCorreos);

		MimeMultipart multipart = new MimeMultipart();

		Properties properties = new Properties();

		int iNumCC = 0;

		if (ccCorreo != null)

			iNumCC = ccCorreo.size();

		try {

			InputStream finDoc = new ByteArrayInputStream(
					sCadenaConfigCorreo.getBytes());

			properties.load(finDoc);

		} catch (IOException e) {

			e.printStackTrace();

			throw new RuntimeException(e.getMessage());

		}

		try {

			_retorno = "l_1";

			Session session = Session.getInstance(properties, null);

			session.setDebug(false);

			_retorno = "l_2";

			MimeMessage msg = new MimeMessage(session);

			msg.setFrom(new InternetAddress(sCorreoRemitente));

			msg.setSubject(sAsunto);

			msg.setSentDate(new Date());

			_retorno = "l_3";

			// Se toman las direcciones web a enviar directo y con copia.

			Address[] to = new Address[toCorreo.size()];

			Address[] cc = null;

			if (iNumCC > 0)

				cc = new Address[iNumCC];

			_retorno = "l_4";

			for (int i = 0; i < toCorreo.size(); i++) {

				to[i] = new InternetAddress(toCorreo.get(i).toString());

			}

			for (int j = 0; j < iNumCC; j++) {

				cc[j] = new InternetAddress(ccCorreo.get(j).toString());

			}

			_retorno = "l_5";

			msg.addRecipients(Message.RecipientType.TO, to);

			if (iNumCC > 0) {

				msg.addRecipients(Message.RecipientType.CC, cc);

			}

			if (sMensaje == null)

				sMensaje = "";

			BodyPart correo = new MimeBodyPart();

			correo.setContent(sMensaje, "text/html");

			_retorno = "l_6";

			// Se adjuntan archivos

			flagAdjuntoArchivos = true;

			System.out.println("antes de adjuntar");

			String carpetaTemporal = adjuntarArchivos(multipart, adjuntos);

			System.out.println("despues de adjuntar");
			if (flagAdjuntoArchivos == false)

				return "0:" + mensajeInterno;

			_retorno = "l_7";

			multipart.addBodyPart(correo);

			msg.setContent(multipart);

			Transport t = session.getTransport("smtps");

			_retorno = "l_8";

			System.out.println("conectando..");
			t.connect(

			properties.getProperty("mail.smtp.host"),

			properties.getProperty("mail.smtp.user"),

			properties.getProperty("mail.smtp.password")

			);

			_retorno = "l_9.0";

			System.out.println("enviando....");

			t.sendMessage(msg, msg.getAllRecipients());

			_retorno = "l_9.1";

			t.close();

			_retorno = "l_10";

			// Se borra carpeta temporal.

			if (carpetaTemporal != null)

			{

				if (carpetaTemporal != null && !carpetaTemporal.equals("")) {

					File carpeta = new File(carpetaTemporal);

					// borrarCarpeta(carpeta);

				}

			}

			_retorno = "1 - OK" + _retorno;

		} catch (Exception ex) {

			if (_retorno == null)

				_retorno = " _ ";

			_retorno = "0 - " + _retorno + " - " + ex.getMessage();

			ex.printStackTrace();

		}
		System.out.println("fin");
		return _retorno;

	}

	/**
	 * 
	 * Convierte una cadena en un vector basada en un separador.
	 * 
	 * @param sCadenaValores
	 *            Cadena de valores, tipo String.
	 * 
	 * @param sSeparador
	 *            Caracter separador, tipo String.
	 * 
	 * @return objVector Lista de resultados en un objeto, del tipo Vector.
	 */

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Vector split(String sCadenaValores, String sSeparador) {

		if (sCadenaValores == null)

			return null;

		if (sCadenaValores.trim().equals(""))

			return null;

		Vector objVector = new Vector();

		int iCantTokens = 0, iNumToken = 0;

		StringTokenizer objToken = new StringTokenizer(sCadenaValores,
				sSeparador);

		iCantTokens = objToken.countTokens();

		for (iNumToken = 0; iNumToken < iCantTokens; iNumToken++)

			objVector.add(objToken.nextToken());

		return objVector;

	}

	/**
	 * 
	 * Recibe el resultSet con los binarios de los archivos, los crea en una
	 * carpeta temporal
	 * 
	 * y los adjunta al correo electronico (primer parametro).
	 * 
	 * @param multipart
	 *            correo electronico al cual se le agregaran los archivos
	 * 
	 * @param rs
	 *            resulSet con la lista de archivos binarios
	 * 
	 * @return ruta de la carpeta temporal creada para guardar los archivos
	 *         generados a partir
	 * 
	 *         del binario. En caso que no exista carpeta creada, se retorna
	 *         vacio.
	 * 
	 * @throws Exception
	 */

	public static String adjuntarArchivos(

	MimeMultipart multipart, List<CorreoAdjuntos> rs) throws Exception {
		System.out.println("adjuntando archivos");
		flagAdjuntoArchivos = false;

		mensajeInterno = "public static String adjuntarArchivos(";

		if (rs == null)

		{

			mensajeInterno = "Sin archivos";

			flagAdjuntoArchivos = true;

			return null;

		} else if (rs.size() < 1) {

		}

		boolean flagTieneTamanio = false;

		SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmssSSS");

		String nombreCarpeta = "";

		mensajeInterno = "while (rs.next()) {";

		for (CorreoAdjuntos adj : rs) {
			mensajeInterno = "if(!flagTieneTamanio){";
			if (!flagTieneTamanio) {

				flagTieneTamanio = true;

				nombreCarpeta = df.format(new Date());

				// Se crea la carpeta por primera y unica vez;

				// boolean bCreado = new File(CARPETA_TEMPORAL + nombreCarpeta)
				// .mkdir();
				boolean bCreado = new File("C:\\Users\\nunezh\\Downloads\\"
						+ nombreCarpeta).mkdir();

				mensajeInterno = "if(" + CARPETA_TEMPORAL + nombreCarpeta + ")";

				if (!bCreado) {

					flagAdjuntoArchivos = false;
					System.out.println(CARPETA_TEMPORAL);

					mensajeInterno = "No se puedo crear carpeta temporal";

					return null;

				}

			}
			String nombre = adj.getNombre();

			InputStream is = adj.getAdjunto();

			// String nombreArchivoTmp = CARPETA_TEMPORAL + nombreCarpeta +
			String nombreArchivoTmp = "C:\\Users\\nunezh\\Downloads\\"
					+ nombreCarpeta + File.separator + nombre;

			System.out.println(">> Nombre archivo : " + nombreArchivoTmp);

			FileOutputStream fos = new FileOutputStream(nombreArchivoTmp);

			mensajeInterno = "int b = 0;";

			int b = 0;

			while ((b = is.read()) != -1)

			{

				mensajeInterno = "fos.write(b);";

				fos.write(b);

			}

//			is.close();

			fos.flush();

			fos.close();

			MimeBodyPart attachFilePart = new MimeBodyPart();

			FileDataSource fds = new FileDataSource(nombreArchivoTmp);

			attachFilePart.setDataHandler(new DataHandler(fds));

			attachFilePart.setFileName(fds.getName());

			multipart.addBodyPart(attachFilePart);
		}

		// se comenta por que da problemas en el objeto package

		// rs.close();

		flagAdjuntoArchivos = true;

		return CARPETA_TEMPORAL + nombreCarpeta;

	}

	/**
	 * 
	 * Borra de forma recursiva todos los elementos de un carpeta.
	 * 
	 * @param folder
	 *            carpeta que contiene archivos hijos que seran borrados.
	 * 
	 * @return TRUE cuando elimina y FALSE en caso contrario
	 */

	public static boolean borrarCarpeta(File folder) {

		if (folder.isDirectory()) {

			String[] children = folder.list();

			for (int i = 0; i < children.length; i++) {

				System.out.println(">>> Iterando file " + i);

				boolean success = borrarCarpeta(new File(folder, children[i]));

				if (!success) {

					return false;

				}

			}

		}

		// La carpeta esta vacia. Ahora puede ser eliminada.

		System.out.println("Carpeta borrada satisfactoriamente");

		return folder.delete();

	}

	/**
	 * 
	 *
	 * 
	 * @param sCorreoRemitente
	 *            correo que se usara como remitente
	 * 
	 * @param sCorreosDestino
	 *            lista de correos electronicos destinatarios separados por un
	 *            caracter,
	 * 
	 *            por ejemplo:
	 *            <i>usuario@compania.com,administrador@compania.com</i>
	 * 
	 * @param sCorreosDestinoCc
	 *            lista de correos electronicos a los cuales se les copia, los
	 *            cuales
	 * 
	 *            estan separados por un caracter, por ejemplo:
	 *            <i>usuariocopia@compania.com,
	 * 
	 *            administradorcopia@compania.com</i>
	 * 
	 * @param sAsunto
	 *            asunto del correo electronico
	 * 
	 * @param sMensaje
	 *            texto que se mostrara en el cuerpo del correo electronico
	 * 
	 * @param sSeparadorCorreos
	 *            caracter que separa la lista de correos destinatarios y
	 *            correos
	 * 
	 *            copia
	 * 
	 * @return texto con el mensaje de validacion
	 */

	public static String validarParametros(

	String sCadenaConfigCorreo,

	String sCorreoRemitente,

	String sCorreosDestino,

	String sCorreosDestinoCc,

	String sAsunto,

	String sMensaje,

	String sSeparadorCorreos) {

		String mensaje = null;

		if (estaVacio(sCadenaConfigCorreo)) {

			return "El texto con los parametros de configuracion esta vacio";

		}

		if (estaVacio(sCorreoRemitente)) {

			return "El texto con el correo remitente esta vacio";

		}

		if (estaVacio(sCorreosDestino)) {

			return "El texto con los correos destinatarios esta vacio";

		}

		if (estaVacio(sAsunto)) {

			return "El texto con el asunto esta vacio";

		}

		/*
		 * 
		 * if(estaVacio(sMensaje)){
		 * 
		 * return "El texto con el mensaje del correo electronico esta vacio";
		 * 
		 * }
		 */

		if (estaVacio(sSeparadorCorreos)) {

			return "El separador de correos esta vacio";

		}

		return mensaje;

	}

	/**
	 * 
	 * Retorna FALSE cuando el texto es diferente de NULL y diferente de vacio.
	 * 
	 * Caso contrario retorna TRUE;
	 * 
	 *
	 * 
	 * @param valor
	 * 
	 *            texto que se evaluara, tipo String
	 * 
	 * @return TRUE o FALSE dependiendo de la condicion cumplida
	 */

	public static boolean estaVacio(String valor) {

		if (valor != null && !valor.equals("") && !valor.equals("null"))

			return false;

		return true;

	}

//	public static void main(String[] args) throws FileNotFoundException {
//		InputStream is = new FileInputStream(
//				"C:\\Users\\nunezh\\Downloads\\skull.ico");
//		InputStream is2 = new FileInputStream(
//				"C:\\Users\\nunezh\\Downloads\\vistamapa.txt");
//		CorreoAdjuntos ca = new CorreoAdjuntos("skull.ico", is);
//		CorreoAdjuntos ca2 = new CorreoAdjuntos("vistamapa.txt", is);
//
//		List<CorreoAdjuntos> adj = new ArrayList<CorreoAdjuntos>();
//		adj.add(ca);
//		adj.add(ca2);
//
//		System.out.println(new NEnvioCorreo().enviarEmail(null,
//				"juridicag@gmail.com", "heiner_23.0@hotmail.com,garyloyola18@gmail.com", null, "Test",
//				"<h1>Test con adjunto</h1> -- juridica  <b>Con varios adjuntos</b>", ",", adj));
//	}

}
